;~int comprimir_archivo (const char *nomb_arch_entrada,	const char *nomb_arch_salida )
%include "macros.mac"
%include "comprimir_buffer.asm"
;~extern comprimir_buffer
extern fopen
extern fread
extern fseek
extern ftell
extern fclose
extern fwrite
extern rewind
extern malloc
extern printf
extern free
global comprimir_archivo

%define nomb_arch_entrada ebp+8    ;const char* 4bytes
%define nomb_arch_salida  ebp+12   ;const char* 4bytes
%define tabla_codificacion_t ebp-4
%define long_codificacion ebp-8
%define tabla_codigos ebp-12
%define dst_size ebp-16
%define dst_buf ebp-20
%define tamanio_arch_entrada ebp-24
%define ptr_buffer ebp-28
%define header ebp-44
%define cant_codigos ebp-48

%define SEEK_END 2	
%define NULL 0
%define codigo_t_size 16
%define codigo_rev 	4 ;valido de codigo_t
%define long_codigo 8 
%define cod_valido 12 
%define codificacion_t_size 9

section .text

r: db "r",0
w: db "w",0


comprimir_archivo:
	convencion_C 48

	abrir_archivo

	;Ahora comprimo el buffer, guardo la compresion en edx
	mov dword [dst_size]	,0
	mov dword [long_codificacion]	,0
	mov dword [tabla_codigos]	,NULL
	mov dword [dst_buf]	,NULL

  ;Ojo! tengo q tratar diferente a los "**", por eso los lea
	lea eax, [long_codificacion]
	lea ebx, [tabla_codigos]
	lea ecx, [dst_size]
	lea edx, [dst_buf]

	
	
	push dword eax 		;long_codificacion 
	push dword ebx		;tabla_codigos
	push dword ecx		;dst_size
	push dword edx 		;dst_buf
	push dword [tamanio_arch_entrada]	;tamanio_arch_entrada
	push dword [ptr_buffer]	;ptr_buffer
	call comprimir_buffer
	cmp eax, 0
	je near comprimir_error

	pop dword [ptr_buffer] 
	pop dword [tamanio_arch_entrada]
	pop dword edx 
	pop dword ecx
	pop dword ebx
	pop dword eax

	;Otra vez, esto es por los molestos "**"
	mov eax,[eax]
	mov ebx,[ebx]
	mov ecx,[ecx]
	mov edx,[edx]
	mov [long_codificacion],eax
	mov [tabla_codigos],ebx
	mov [dst_size],ecx
	mov [dst_buf],edx

	
	;libero buffer
	push dword [ptr_buffer]
	call free
	add esp,4
	
	;~A partir de la tabla de codigos, tengo que crear una lista de codificacion_t
	; edi => cantidad de codigos
	xor edi,edi
	mov ecx, [tabla_codigos] 
	mov eax, 256
	ciclo:
		cmp dword [ecx + cod_valido], 1
		jne next
		inc edi
		next:
			add ecx, codigo_t_size
		dec eax
		cmp eax,0
		jne ciclo
	

	; genero la tabla de codificacion_T
	
	lea esi, [edi*codificacion_t_size] ;gracias al nasm puedo multiplicar por 9
	mov [cant_codigos], edi ;lo guardo para despues
	push esi
	call malloc
	pop esi
	mov  [ tabla_codificacion_t ], eax
		

	;ciclo que rellena la tabla de cod_t
	mov ebx, [ tabla_codificacion_t ]
	mov ecx, [tabla_codigos] 
	xor eax,eax
	ciclo2:
		cmp dword [ecx + cod_valido], 1
		jne next2
		mov [ebx], al  ;simbolo
		add ebx,1
		mov edx, [ecx]
		mov [ebx], edx
		add ebx, 4
		mov edx, [ecx+long_codigo]
		mov [ebx], edx 
		add ebx, 4
		next2:
			add ecx, codigo_t_size
		inc eax
		cmp eax,256
		jne ciclo2

	;Creo el archivo de salida con permisos de escritura
	push w
	push dword [nomb_arch_salida]
	call fopen
	add esp, 8

	;en ebx => puntero a archivo de salida
	mov ebx,eax

	;Armo el header
	mov ecx, [tamanio_arch_entrada]
	mov [header], ecx 		;tam_original
	mov ecx, [long_codificacion]
	mov [header+4], ecx		;long_codificacion
	mov ecx, [cant_codigos]
	mov [header+8], ecx		;cant_codigos
	lea ecx, [ecx*codificacion_t_size + 16]
	mov [header+12], ecx  ;offset_codificacion
	
	;escribo el header en el archivo
	push ebx ;salida
	push 1   ;sizeof char
	push 16  ;sizeof header
;!!
	lea ecx, [header]
	push ecx
	;!!
	call fwrite
	add esp, 12
	pop ebx

	;Ahora guardo la tabla de codigos
	push ebx ;salida
	push dword [cant_codigos]
	push codificacion_t_size
	push dword [ tabla_codificacion_t ]
	call fwrite
	add esp,12
	pop ebx
	
	;Y ahora los datos comprimidos
	push ebx ;salida
	push dword [dst_size]
	push 1
	push dword [ dst_buf ]
	call fwrite
	add esp,12
	pop ebx

	;Cierro el archivo de salida, libero memoria, etc
	push ebx
	call fclose
	add esp,4

	push dword [tabla_codigos]
	call free
	add esp,4

	push dword [dst_buf]
	call free
	add esp,4

	push dword [tabla_codificacion_t]
	call free
	add esp,4

	mov eax, 1  ;Sin errores!
fin_comp_archivo:	
	convencion_C_fin 48
	ret

comprimir_error:
	add esp,24
	print_error "No se pudo comprimir!"
	jmp fin_comp_archivo
	
abrir_error:


	print_error "No se pudo abrir el archivo!"
	jmp fin_comp_archivo
